#include "mysocket.h"




bool cSocket::sendmsg(string msg)
{
    
    ssize_t bytesSent = send(clientsocketid, msg.c_str(), msg.length(), 0);
    if (bytesSent == -1) {
        perror("socket: Failed to send data");
        close(clientsocketid);
        return false;//exit(EXIT_FAILURE);
    }else
    {
        cout<<"socket: "<<bytesSent<<"Bytes sended\n";
    }

    return true;
};

bool cSocket::init()
{

    struct sockaddr_in serverAddr;
    // Create the client socket
    clientsocketid = socket(AF_INET, SOCK_STREAM, 0);
    if (clientsocketid == -1) {
        perror("socket: Failed to create client socket");
        return false;//exit(EXIT_FAILURE);
    }

    // Configure the server address
    memset(&serverAddr, 0, sizeof(serverAddr));
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_port = htons(port);
    inet_pton(AF_INET, ip.c_str(), &serverAddr.sin_addr);

    // Connect to the server
    if (connect(clientsocketid, (struct sockaddr*)&serverAddr, sizeof(serverAddr)) == -1) {
        perror("socket: Failed to connect to server");
        close(clientsocketid);
        return false;//exit(EXIT_FAILURE);
    }else
    {
        string teststr = "Hello!";
        ssize_t bytesSent = send(clientsocketid, teststr.c_str(), sizeof(teststr), 0);
        if (bytesSent == -1) {
            perror("socket: Failed to send data");
            close(clientsocketid);
            return false;//exit(EXIT_FAILURE);
        }else
        {
            cout<<"socket: "<<bytesSent<<"Bytes sended\n";
        }


        // Receive the echoed message from the server
        ssize_t bytesReceived = recv(clientsocketid, buffer, sizeof(buffer), 0);
        if (bytesReceived == -1) {
            perror("socket: Failed to receive data");
            close(clientsocketid);
            return false;//exit(EXIT_FAILURE);
        }


        // Output the received message
        std::cout << "socket: Received from server: " << buffer << std::endl;
    }

    return true;
};



string cSocket::recvmsg()
{

    return string("recv");
};



bool sSocket::sendmsg(string msg, int clientsocketid)
{

    ssize_t bytesSent = send(clientsocketid, msg.c_str(), msg.length(), 0);
        if (bytesSent == -1) {
            perror("socket: Failed to send data");
            close(clientsocketid);
            return false;//exit(EXIT_FAILURE);
        }else
        {
            cout<<"socket: "<<bytesSent<<"Bytes sended\n";
        }

    return true;

    return true;
};



string sSocket::recvmsg()
{

    return string("recv");
};

bool sSocket::init()
{

    struct sockaddr_in serverAddr;

    // Create the server socket
    serversocketid = socket(AF_INET, SOCK_STREAM, 0);
    if (serversocketid == -1) {
        perror("socket: Failed to create server socket");
        exit(EXIT_FAILURE);
    }

    // Configure the server address
    memset(&serverAddr, 0, sizeof(serverAddr));
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_port = htons(port);
    serverAddr.sin_addr.s_addr = htonl(INADDR_ANY);

    // Bind the server socket
    if (bind(serversocketid, (struct sockaddr*)&serverAddr, sizeof(serverAddr)) == -1) {
        perror("socket: Failed to bind server socket");
        close(serversocketid);
        exit(EXIT_FAILURE);
    }

    // Listen for incoming connections
    if (listen(serversocketid, 5) == -1) {
        perror("socket: Failed to listen on server socket");
        close(serversocketid);
        exit(EXIT_FAILURE);
    }

    return true;
};

void sSocket::handleclient(int client_socket) {

    char buffer[BUFFER_SIZE] = {0};
    ssize_t bytes_received = recv(client_socket, buffer, BUFFER_SIZE - 1, 0);
    if (bytes_received > 0) {
        buffer[bytes_received] = '\0';
        std::cout << "socket: Received from client: " << buffer << std::endl;
    } else if (bytes_received == 0) {
        std::cout << "socket: 0 byte recved" << std::endl;
        return;
    } else {
        std::cout << "socket: Receive error: " << strerror(errno) << std::endl;
        return;
    }

    string recvedcmd(buffer);

    if(recvedcmd!=string("Hello!"))
    {
        auto it = clientsocketidname.find(client_socket);

        if (it != clientsocketidname.end()) {
            // user first connect to server
            istringstream iss(buffer);
            string token;
            iss >> token;
            iss >> token;
            clientsocketidname[client_socket]=token;
            cout<<"new user "<<token<<" login"<<endl;
        } else {
            // user had connect to server
            istringstream iss(buffer);
            string token;
            iss >> token;
            if(token==string("logout"))
            {
                // logout cmd
                cout<<"socket: client logout close socket\n";
                close(client_socket);
                clientsocketidname.erase(client_socket);
            }else{

                //socket id bind with user name then send by socket id 
                //other cmd
                //ping test 
                //communicate
                //list history

                istringstream iss(buffer);
                string token;
                iss >> token;
                cout<<"socket: logined user cmd"<<endl;

                //the middle one interconnect should have some info
                // choose to give cmd string to sql and parse in sql
                // parse cmd
                cmdptr = cfs.getcmdptr(recvedcmd);
                
                thesql* sqlptr = new mysql();

                cmdptr->cmd2sql();
                cmdptr->function=string(token);

                sqlptr->function=cmdptr->function;

                sqlptr->table=cmdptr->table;
                sqlptr->key=cmdptr->key;
                sqlptr->value=cmdptr->value;
                sqlptr->wherekey=cmdptr->wherekey;
                sqlptr->wherevalue=cmdptr->wherevalue;
                sqlptr->cmd2sql();


                //cout<< (*sqlptr);
                // push into task queue
                sqltask sqltask(sqlptr);
                cout <<"mysqlobj:"<< * (mysql*)sqltask.argu;
                threadpoolptr->addtask(sqltask);

            }
        }
    }else{
        send(client_socket, buffer, bytes_received, 0);
    }
    return ;
}

bool sSocket::epolldeal()
{

    // 创建 epoll 文件描述符
    int epoll_fd;
    if ((epoll_fd = epoll_create1(0)) == -1) {
        perror("Epoll: Epoll create failed");
        close(serversocketid);
        exit(EXIT_FAILURE);
    }

    // 注册监听事件
    struct epoll_event ev;
    ev.events = EPOLLIN | EPOLLET; // 边缘触发模式
    ev.data.fd = serversocketid;

    if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, serversocketid, &ev) == -1) {
        perror("Epoll: Epoll add failed");
        close(serversocketid);
        close(epoll_fd);
        exit(EXIT_FAILURE);
    }

    int num_events;
    struct epoll_event events[EPOLL_SIZE];
    // 循环处理事件
    while (1) {

        num_events = epoll_wait(epoll_fd, events, MAX_EVENTS, -1);
        cout<<"Epoll msg:"<<num_events<<"req recv\n";


        if (num_events == -1) {
            perror("Epoll: Epoll wait failed");
            continue;
        }

        struct sockaddr_in serverAddr;

        for (int i = 0; i < num_events; i++) {
            if (events[i].data.fd == serversocketid) {
                cout<<"connect req, accept\n";

                // 接受新的连接
                socklen_t client_len = sizeof(struct sockaddr_in);
                
                int tempsocketid = accept(serversocketid, (struct sockaddr *)&serverAddr, &client_len);
                if (tempsocketid == -1) {
                    perror("Accept failed");
                    continue;
                }

                // 注册新连接的监听事件
                ev.events = EPOLLIN | EPOLLET;
                ev.data.fd = tempsocketid;
                if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, tempsocketid, &ev) == -1) {
                    perror("Epoll: Epoll add failed");
                    close(tempsocketid);
                    continue;
                }
                std::cout << "New client connected: " << inet_ntoa(serverAddr.sin_addr) << ":" << ntohs(serverAddr.sin_port) << std::endl;

            } else {
                // 处理客户端的数据
                cout<<"message req, recv\n";
                handleclient(events[i].data.fd);
            }

        }

    }

    return true;
};
